home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Freeware 1998 June
/
SGI Freeware 1998 June.iso
/
dist
/
fw_UMINNgopher.idb
/
usr
/
freeware
/
src
/
gopher_1.12
/
gopherd
/
ftp.c.z
/
ftp.c
Wrap
C/C++ Source or Header
|
1997-09-09
|
14KB
|
527 lines
/********************************************************************
* $Author: drich $
* $Revision: 1.1 $
* $Date: 1995/10/03 04:08:28 $
* $Source: /proj/freeware1.0/gopher1.12/src/gopherd/RCS/ftp.c,v $
* $Status: $
*
* Paul Lindner, University of Minnesota CIS.
*
* Copyright 1991, 1992 by the Regents of the University of Minnesota
* see the file "Copyright" in the distribution for conditions of use.
*********************************************************************
* MODULE: ftp.c
* Routines to translate gopher protocol to ftp protocol.
*********************************************************************
* Revision History:
* $Log: ftp.c,v $
* Revision 1.1 1995/10/03 04:08:28 drich
* gopher 1.2 check-in
*
* Revision 1.2 1993/01/11 23:18:09 lindner
* Changed password to be the host of the remote client, not the gateway.
*
* Revision 1.1 1992/12/10 23:13:27 lindner
* gopher 1.1 release
*
*
*********************************************************************/
/* -------------------------------------------------
* g2fd.c Gopher to FTP gateway daemon.
* Version 0.3 Hacked up: April 1992. Farhad Anklesaria.
* Based on a Perl story by John Ladwig.
* Based on a Perl story by Farhad Anklesaria.
*
* Modified by Greg Smith, Bucknell University, 24 Nov 1992
* to handle multiline status replies.
*
---------------------------------------------------- */
#include "gopherd.h"
#include <signal.h>
#include <stdio.h>
#define GFILE 0 /* Gopher item types */
#define GDIR 1
#define GBINHEX 4
#define GDOSB 5
#define GUNIXB 9
#define GIMAGE "I"
#define GSOUND "s"
#define SLEN 255 /* Generic small buffer length */
#define TMOUT 180 /* 3 minutes is plenty long enough */
int GLOBALsockfd; /* For cleanup */
char *appname;
char ftptmp[SLEN] = LIST;
char query[BUFSIZ]; /* input redirected by inetd */
char *host, *thing; /* pointers into query */
int gettingFile = 1;
int gettingBinary = 0;
int childpid;
/*** Some forward declarations ***/
boolean NotText();
int Abort();
boolean IsBinaryType();
void GenerateUniqueFiles();
void GopherType();
void Cleanup();
void RoundEmUp();
void FailErr();
int getreply();
/**************************/
int
getreply(theStream,inputline,maxlen)
int theStream;
char *inputline;
int maxlen;
{
int code = 0;
char origcode[4];
readline(theStream, inputline, maxlen);
if (DEBUG) printf(inputline);
strncpy(origcode, inputline, 3); /*** Stash away the original code ***/
while (inputline[3] == '-') {
if (readline(theStream, inputline, maxlen)<=0)
return(-1);
if (DEBUG) printf(inputline);
if (!isdigit(inputline[0]) && !isdigit(inputline[1]) &&
!isdigit(inputline[2]))
inputline[3] = '-';
else
/*** Keep going if response code isn't the same as original **/
if (strncmp(origcode, inputline, 3) != 0)
inputline[3] = '-';
}
return (0);
}
void
SendFtpQuery(sockfd, query)
char *query;
{
int sLen, termCh;
char *at, *cp;
char inputline[512];
char ipnum[64];
char buf[1600]; /*** Nice MTU size ***/
int tmpfd;
int ftp_control, ftp_data;
int ftp_dataport, nRead;
GopherObj *gs;
/*** hook onto the gs code to do our ftp socket connects ***/
gs = GSnew();
/** Get ready for some cleanup action **/
signal(SIGPIPE, Cleanup);
signal(SIGINT, Cleanup);
signal(SIGALRM, Cleanup);
if (DEBUG)
printf("The full query was %s\n", query);
if ((sLen = strlen(query)) <= 2) Abort(sockfd,"No host name specified.");
host = query;
at = strchr(query, '@');
if (at == NULL)
Abort(sockfd, "Not a valid ftp query.");
GenerateUniqueFiles(ftptmp);
tmpfd = uopen(ftptmp, O_RDWR|O_CREAT,0755);
if (tmpfd < 0)
Abort(sockfd, "Sorry, out of tmp transfer space!");
thing = at + 1;
*at = '\0'; /*Sneakily chop it into two strings*/
sLen = strlen(thing);
termCh = thing[sLen - 1]; /* Grab possible end char: / etc */
if ((termCh == '*') || (termCh == '@')) /* || (termCh == '/') */
thing[sLen - 1] = '\0';
if (DEBUG)
printf("At this point host: %s thing: %s\n", host, thing);
/*** Open an ftp control connection ***/
GSsetHost(gs, host);
GSsetPort(gs, 21);
ftp_control = GSconnect(gs);
if (ftp_control < 0)
Abort(sockfd, "unable to connect to ftp server!");
/*** Strip off the connection message ***/
getreply(ftp_control,inputline,sizeof inputline);
if (*inputline != '2')
/*** Some sort of error, urg! ***/
Abort(sockfd, inputline +3);
/*** Send username ***/
writestring(ftp_control, "USER anonymous\r\n");
getreply(ftp_control,inputline,sizeof inputline);
if (*inputline != '3')
/*** Some sort of error, urg! ***/
Abort(sockfd, inputline +3);
/** Send password***/
writestring(ftp_control, "PASS -gopher@");
inet_netnames(sockfd, inputline, ipnum);
writestring(ftp_control, inputline);
writestring(ftp_control, "\r\n");
if (DEBUG) printf("Password was -gopher@%s\n", inputline);
getreply(ftp_control,inputline,sizeof inputline);
if (*inputline != '2')
/*** Some sort of error, urg! ***/
Abort(sockfd, inputline +3);
/**** Send PASV and set up the data port ***/
writestring(ftp_control, "PASV\r\n");
getreply(ftp_control,inputline,sizeof inputline);
if (strncmp(inputline, "227", 3))
Abort(sockfd,inputline +3);
/*** Find out the port number of the data connection ***/
inputline[strlen(inputline)] = '\0'; /** Zap the right paren **/
cp = strrchr(inputline, ','); /** lower order octet **/
if (cp == NULL) Abort(sockfd,"PASV failed- cannot ftp!");
*cp = '\0';
cp ++;
ftp_dataport = atoi(cp);
cp = strrchr(inputline, ','); /** upper octet **/
if (cp == NULL) Abort(sockfd,"PASV failed- cannot ftp!");
*cp = '\0';
cp ++;
ftp_dataport = atoi(cp) * 256 + ftp_dataport;
if (DEBUG) printf("Data port is %d\n", ftp_dataport);
GSsetPort(gs, ftp_dataport);
ftp_data = GSconnect(gs);
if (ftp_data < 0)
Abort(sockfd,"Unable to establish data connection!");
if (termCh == '/') { /* We have a directory */
gettingFile = 0;
writestring(ftp_control, "NLST -LF ");
if (strlen(thing) > 0)
writestring(ftp_control, thing);
writestring(ftp_control, "\r\n");
getreply(ftp_control,inputline,sizeof inputline);
if (*inputline != '1')
Abort(sockfd,inputline + 4);
}
else { /* We have a file */
gettingFile = 1;
if (gettingBinary = IsBinaryType(thing)) {
writestring(ftp_control, "TYPE I\r\n");
getreply(ftp_control,inputline,sizeof inputline);
if (*inputline != '2')
Abort(sockfd,"Unable to transfer files in binary");
}
writestring(ftp_control, "RETR ");
writestring(ftp_control, thing);
writestring(ftp_control, "\r\n");
getreply(ftp_control,inputline,sizeof inputline);
if (*inputline != '1')
Abort(sockfd,inputline + 4);
}
/*** Transfer the data... ***/
while ((nRead = read(ftp_data, buf, sizeof buf)) > 0)
writen(tmpfd, buf, nRead);
close(ftp_data);
getreply(ftp_control,inputline,sizeof inputline);
if (*inputline != '2')
Abort(sockfd,inputline + 3);
writestring(ftp_control, "QUIT\r\n");
getreply(ftp_control,inputline,sizeof inputline);
if (*inputline != '2')
Abort(sockfd,inputline + 3);
close(ftp_control);
}
/*--------------------------------*/
void
TranslateResults(sockfd)
int sockfd;
{
FILE *fp, *OpenOrDie();
char buf[BUFSIZ], theName[SLEN];
int fd, nRead, checkIt;
char outputline[512];
checkIt = 1;
signal(SIGPIPE, Cleanup);
signal(SIGINT, Cleanup);
if (gettingFile) {
if (gettingBinary) { /* icky binary file */
if (DEBUG)
printf("Whoa! That's a binary file\n");
fp = OpenOrDie(ftptmp, "r");
fd = fileno(fp);
if (DEBUG)
printf("fd %d\n",fd);
while ((nRead = read(fd, buf, sizeof buf)) > 0)
writen(sockfd, buf, nRead);
writen(sockfd, buf, nRead);
fclose(fp);
} else { /* must be a nice texty file */
fp = OpenOrDie(ftptmp, "r");
while (fgets(buf, sizeof buf, fp) != NULL) {
if (checkIt) { /* Just peek at it once */
checkIt = 0;
if (NotText(buf)) {
fclose(fp);
Abort(sockfd,"Sorry. File does not appear to contain text.");
}
}
ZapCRLF(buf);
FailErr(writestring(sockfd, buf));
FailErr(writestring(sockfd, "\r\n"));
}
fclose(fp);
FailErr(writestring(sockfd,".\r\n"));
}
} else { /* Must be a directory */
fp = OpenOrDie(ftptmp, "r");
while (fgets(buf, sizeof buf, fp) != NULL) {
ZapCRLF(buf);
GopherType(buf, theName);
sprintf(outputline, "%s\tftp:%s@%s%s\t%s\t%d\r\n", theName,
host, thing, buf, Zehostname, GopherPort);
FailErr(writestring(sockfd, outputline));
}
fclose(fp);
FailErr(writestring(sockfd, ".\r\n"));
}
Cleanup();
}
/*--------------------------------*/
FILE *OpenOrDie(file, mode)
char *file, *mode;
{
FILE *fp, *fopen();
if ((fp = ufopen(file, mode,0755)) != NULL) {
return(fp);
} else {
Cleanup();
exit(-1);
}
return(NULL); /** Shouldn't get here **/
}
/*--------------------------------*/
boolean
NotText(buf)
char * buf;
{
int max; char *c;
if ((max = strlen(buf)) >= (BUFSIZ - 50)) max = BUFSIZ - 50;
for (c = buf; c < (buf + max); c++) {
if (*c > '~') return(TRUE);
}
return(FALSE);
}
/*--------------------------------*/
int
Abort(sockfd, complaint)
int sockfd;
char *complaint;
{
char errmsg[512];
sprintf(errmsg, "3 Error: %s\r\n.\r\n", complaint);
writestring(sockfd, errmsg);
fflush(stdout);
Cleanup();
exit(1);
}
/*--------------------------------*/
boolean
IsBinaryType(thing)
char *thing;
{
static char *binExt[] = {
".zip", ".zoo", ".arj", ".arc", ".lzh", ".hyp", ".pak", ".exe", ".com",
".ps", ".gif", ".pict", ".pct", ".tiff", ".tif", ".tar", ".Z", ".pict", ".au"
};
int extType, i;
for (extType = 0; extType < 19; extType++) {
i = strcasecmp(thing + strlen(thing) - strlen(binExt[extType]),
binExt[extType]);
if (i == 0) return(TRUE);
}
return(FALSE);
}
/*--------------------------------*/
void
GenerateUniqueFiles(tmpList)
char *tmpList;
{
char *s;
int pid;
pid = getpid();
s = strchr(tmpList, '+');
sprintf(s, "%d", pid);
}
/*--------------------------------*/
void
GopherType(buf, theName)
char *buf, *theName;
{
static char ext4[] = ".hqx";
static char *exts[] = {".au", ".snd"};
static char *extI[] = {".gif", ".pict", ".tiff", ".tif", ".pcx"};
static char *ext5[] = {".zip", ".zoo", ".arj", ".arc", ".lzh", ".hyp",
".pak", ".exe", ".com", ".ps", ".pct"};
static char *ext9[] = {".tar", ".Z"};
int extType, i, last;
char tmpName[SLEN];
last = strlen(buf) -1;
strcpy(tmpName, buf);
if (buf[last] == '/') {
tmpName[last] = '\0';
sprintf(theName, "%d%s", GDIR, tmpName);
return;
}
if ((buf[last] == '*') || (buf[last] == '@')) { /* Hack out * and @ */
buf[last] = '\0';
tmpName[last] = '\0';
}
/* At this point we're looking at a file */
if (strcasecmp(buf + strlen(buf) - strlen(ext4), ext4) == 0) { /* BinHex? */
sprintf(theName, "%d%s", GBINHEX, tmpName);
return;
}
for (extType = 0; extType < 11; extType++) { /* PC garbage? */
i = strcasecmp(buf + strlen(buf) - strlen(ext5[extType]),
ext5[extType]);
if (i == 0) {
sprintf(theName, "%d%s", GDOSB, tmpName);
return;
}
}
for (extType = 0; extType < 2; extType++) { /* unix binary? */
i = strcasecmp(buf + strlen(buf) - strlen(ext9[extType]),
ext9[extType]);
if (i == 0) {
sprintf(theName, "%d%s", GUNIXB, tmpName);
return;
}
}
for (extType = 0; extType < 5; extType++) { /** Image? **/
i = strcasecmp(buf + strlen(buf) - strlen(extI[extType]),
extI[extType]);
if (i == 0) {
sprintf(theName, "%s%s", GIMAGE, tmpName);
return;
}
}
for (extType = 0; extType < 2; extType++) { /** Image? **/
i = strcasecmp(buf + strlen(buf) - strlen(exts[extType]),
exts[extType]);
if (i == 0) {
sprintf(theName, "%s%s", GSOUND, tmpName);
return;
}
}
sprintf(theName, "%d%s", GFILE, tmpName);
return; /* Some other and hopefully text file */
}
/*--------------------------------*/
void
Cleanup()
{
unlink(ftptmp);
if (DEBUG)
printf("Cleaning up %s\n", ftptmp);
exit(1);
}
/*--------------------------------*/
void
RoundEmUp()
{
kill(childpid, SIGKILL);
Cleanup();
}
/*--------------------------------*/
void
FailErr(result)
int result;
{
if (result < 0) {
Cleanup();
}
}
/*--------------------------------*/